/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

#include "../Types.h"
#include "../TypeMap.h"
#include "../ReferenceTypeMap.h"
#include "../TypeHelper.h"

#include "../util/intmap.h"
#include "../util/chunkbuffer.h"

#include "../common/BigEndianUnsignedByte.h"
#include "../common/BigEndianSignedInteger.h"
#include "../common/U8Ascii.h"
#include "../common/U16ArrayByte.h"

#include "TypeTriple.h"
#include "TypeLink.h"
#include "TypeClient.h"
#include "ProtocolTypeMap.h"

void type_client_init( type_client * client, type_library * library, type_link link, void * linkData )
{
	client->library = library;
	protocol_type_map_init( &client->pmap, library );
	client->link = link;
	client->linkData = linkData;
}

int type_client_resolve_type( type_client * client, type_name * name, type_buffer * definition )
{	
	chunk_buffer baos;
	chunk_buffer bais;
	type_output_stream tmos;
	type_input_stream tmis;
	
	// Write the name and definition to the request body.	
	chunk_buffer_init( &baos);
	type_output_init( &tmos, &client->pmap, &chunkBufferWriter, &baos );
	
	uint8_t type = MAP;
	type_output_write_named_object( &tmos, &uint8_name, &type );
	type_output_write_named_object( &tmos, &u8ascii_name, name->name );
	u16array array;
	array.size = definition->size;
	array.data = definition->data;
	type_output_write_named_object( &tmos, &u16binary_name, &array );
	chunk_buffer_close( &baos );
	
	chunk_buffer_init( &bais );
	// Send the request to the server.
	client->link( client->linkData, &chunkBufferReader, &baos, &chunkBufferWriter, &bais );

	type_input_init( &tmis, &client->pmap, &chunkBufferReader, &bais );
	type_input_read_named_object( &tmis, &uint8_name );
	uint8_t msgType = type_stack_get_u8( type_input_stack( &tmis ) );
	if ( msgType != MAP ) 
		return -1;
	type_input_read_named_object( &tmis, &sint32_name );
	int value = type_stack_get_s32( type_input_stack( &tmis ) );
	
	chunk_buffer_clean( &baos );
	chunk_buffer_clean( &bais );

	return value;
}

int type_client_reserve_type( type_client * client, type_name * name )
{		
	chunk_buffer baos;
	chunk_buffer bais;
	type_output_stream tmos;
	type_input_stream tmis;
	
	// Write the name and definition to the request body.	
	chunk_buffer_init( &baos);
	type_output_init( &tmos, (type_map*) &client->pmap, &chunkBufferWriter, &baos );
	uint8_t type = MAPRES;
	type_output_write_named_object( &tmos, &uint8_name, &type );		
	type_output_write_named_object( &tmos, &u8ascii_name, name->name );
	chunk_buffer_close( &baos );
			
	chunk_buffer_init( &bais );
	// Send the request to the server.
	client->link( client->linkData, &chunkBufferReader, &baos, &chunkBufferWriter, &bais );
	
	type_input_init( &tmis, &client->pmap, &chunkBufferReader, &bais  );	
	type_input_read_named_object( &tmis, &uint8_name );
	uint8_t msgType = type_stack_get_u8( type_input_stack( &tmis ) );
	if ( msgType != MAPRES ) return -1;
	
 	type_input_read_named_object( &tmis, &sint32_name );
	int32_t value = type_stack_get_s32( type_input_stack( &tmis ) );
	chunk_buffer_close( &bais );

	chunk_buffer_clean( &baos );
	chunk_buffer_clean( &bais );
	return value;
}

int type_client_resolve_reverse( type_client * client, type_triple * triple, int id )
{		
	chunk_buffer baos;
	chunk_buffer bais;
	type_output_stream tmos;
	type_input_stream tmis;
	
	// Write the name and definition to the request body.	
	chunk_buffer_init( &baos);
	type_output_init( &tmos, &client->pmap, &chunkBufferWriter, &baos );
	uint8_t type = MAPREV;
	type_output_write_named_object( &tmos, &uint8_name, &type );		
	type_output_write_named_object( &tmos, &sint32_name, &id );
	chunk_buffer_close( &baos );
			
	chunk_buffer_init( &bais );
	// Send the request to the server.
	client->link( client->linkData, &chunkBufferReader, &baos, &chunkBufferWriter, &bais );
	
	type_input_init( &tmis, &client->pmap, &chunkBufferReader, &bais );	
	type_input_read_named_object( &tmis, &uint8_name );
	uint8_t msgType = type_stack_get_u8( type_input_stack( &tmis ) );
	if ( msgType != MAPREV ) return -1;
	
	type_input_read_named_object( &tmis, &u8ascii_name );
	char * name = (char *) type_stack_get_ptr( type_input_stack( &tmis ) );
	type_name * tname = type_malloc( sizeof( type_name ) );
	tname->name = name;
	tname->hash = 0;
	type_input_read_named_object( &tmis, &u16binary_name );
	u16array * array = (u16array*) type_stack_get_ptr( type_input_stack( &tmis ) );
	type_buffer * definition = type_malloc( sizeof( type_buffer ) );
	definition->size = array->size;
	definition->data = array->data;
	type_free( definition );
	
	triple->id = id;
	triple->name = tname;
	triple->definition = definition;

	return TYPE_OK;
}


